#include "httplib.h"
#include "json.hpp"

#include "Messenger.h"
#include "Glog.h"
#include "mainwindow.h"
using namespace httplib;
using nlohmann::json;

inline double getWebTimestamp()
{
    Client client("api.m.taobao.com",80,1);
    std::shared_ptr<Response> res=client.Get("/rest/api3.do?api=mtop.common.getTimestamp");
    if(!res) return -1;
    try{
        auto content=json::parse(res->body);
        auto time=content["data"]["t"];
        return std::stod(time.get<std::string>())/1000;
    }
    catch(std::exception& e){
        return -2;
    }
}

inline void signal_handler(int sig)
{
    LOG(ERROR)<<"Received SIGPIPE";
}

typedef std::pair<const Request&,Response&> RequestResponse;
class HttpService
{
public:
    HttpService(){
        _server.Get("/",[this](const Request& req,Response& res){
            res.set_redirect("/ver");
        });

        _server.Get("/ver",[this](const Request& req,Response& res){
            json ret={{"code","0"},{"ver", 1}, {"message","success"}};
            res.set_content(ret.dump(), "application/json");
        });


        _server.Post("/planRoute",[this](const Request& req,Response& res) {
            //            GSLAM::Messenger::instance().publish("sbt.task.post",RequestResponse(req,res));

            sv::Svar reqSvar = sv::Svar::parse_json(req.body);
            std::vector<GSLAM::Point3d> coordinates;
            GSLAM::Point3d landingPoint;

            double image_focal = 3000;
            double image_width = 4000;
            double fly_height;
            double overlap;
            double angle;
            double gap;

            if(reqSvar.exist("height"))
                fly_height = reqSvar["height"].castAs<double>();

            if(reqSvar.exist("height"))
                overlap = (reqSvar["overlap"][1].castAs<double>())/100;

            if(reqSvar.exist("angle"))
                angle = reqSvar["angle"].castAs<double>();

            gap = get_gap_from_camera_overlap(image_focal,image_width,fly_height,overlap);

            if(reqSvar.exist("poly"))
                if(reqSvar["poly"].exist("geometry"))
                    if(reqSvar["poly"]["geometry"].exist("coordinates")) {
                        for(int i=0;i<reqSvar["poly"]["geometry"]["coordinates"].size();i++) {
                            GSLAM::Point3d coordinate;

                            double x = reqSvar["poly"]["geometry"]["coordinates"][i][0].as<double>();
                            coordinate.setX(x);

                            double y = reqSvar["poly"]["geometry"]["coordinates"][i][1].as<double>();
                            coordinate.setY(y);

                            double z = 0;
                            coordinate.setZ(z);

                            coordinates.push_back(coordinate);
                        }
                    }
            if(reqSvar.exist("landing_point") && reqSvar.exist("height")) {
                double x = reqSvar["landing_point"][0].as<double>();
                landingPoint.setX(x);

                double y = reqSvar["landing_point"][1].as<double>();
                landingPoint.setY(y);

                double z = reqSvar["height"].castAs<double>();
                landingPoint.setZ(z);
            }

            coordinates = ploy_to_path(coordinates,landingPoint,gap,angle);

            QJsonObject responseData;
            responseData["sno"] = 0;
            responseData["result"] = 0;
            QJsonObject dataObject;
            QJsonArray coordinatesArray_response;
            for(int i=0; i<coordinates.size(); i++)
            {
                QJsonArray temp;
                temp.append(coordinates[i].x);
                temp.append(coordinates[i].y);
                temp.append(coordinates[i].z);
                coordinatesArray_response.append(temp);
            }

            dataObject["coordinates"] = coordinatesArray_response;
            dataObject["type"] = "LineString";
            responseData["data"] = dataObject;
            responseData["message"] = "Success";
            // 发送响应数据给客户端
            QJsonDocument response(responseData);
            std::string jsonString = response.toJson(QJsonDocument::Compact);
            res.set_content(jsonString, "application/json");
        });








        //        _server.Get("/task/([^/]*)",[this](const Request& req,Response& res){
        //            GSLAM::Messenger::instance().publish("sbt.task.get",RequestResponse(req,res));
        //        });

        //        _server.Get("/task",[this](const Request& req,Response& res){
        //            GSLAM::Messenger::instance().publish("sbt.task.get",RequestResponse(req,res));
        //        });

        //        _server.Delete("/task/[^/]*",[this](const Request& req,Response& res){
        //            GSLAM::Messenger::instance().publish("sbt.task.delete",RequestResponse(req,res));
        //        });

    }

    ~HttpService(){
        _server.stop();
        if(_listenThread.joinable()) _listenThread.join();
    }

    void listen(const char *host, int port){
        _listenThread=std::thread([this,host,port](){
            int portTmp=port;
            while(!_server.bind_to_port(host,portTmp)) portTmp++;
            LOG(INFO)<<"Http service started at 0.0.0.0:"<<portTmp;
            GSLAM::Messenger::instance().publish("sbt.http_port",portTmp);
#ifdef __unix__
            signal(SIGPIPE, signal_handler);
#endif
            _server.listen_after_bind();
        });
    }

    httplib::Server       _server;
    std::thread           _listenThread;
};
